package com.aizhixin.lab.course.classes.service;

import lombok.extern.slf4j.Slf4j;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.aizhixin.lab.common.core.ApiReturnConstants;
import com.aizhixin.lab.common.core.DataValidity;
import com.aizhixin.lab.common.core.UserInforCore;
import com.aizhixin.lab.common.domain.PageDomain;
import com.aizhixin.lab.common.dto.SortDTO;
import com.aizhixin.lab.common.utils.PageJdbcUtil;
import com.aizhixin.lab.company.domain.AccountDomain;
import com.aizhixin.lab.company.domain.QueryUserDomain;
import com.aizhixin.lab.company.service.UserService;
import com.aizhixin.lab.course.classes.domain.CourseClassDomain;
import com.aizhixin.lab.course.classes.dto.CourseClassDTO;
import com.aizhixin.lab.course.classes.dto.CourseInfoDTO;
import com.aizhixin.lab.course.classes.dto.InitLabReportDTO;
import com.aizhixin.lab.course.classes.entity.CourseClass;
import com.aizhixin.lab.course.classes.entity.CourseClassStu;
import com.aizhixin.lab.course.classes.entity.LabClass;
import com.aizhixin.lab.course.classes.repository.CourseClassRepository;
import com.aizhixin.lab.course.course.entity.Course;
import com.aizhixin.lab.course.course.service.CourseService;

@Slf4j
@Service
@Transactional
public class CourseClassService {
    @Autowired
    private CourseClassRepository courseClassRepository;
    @Autowired
    private CourseClassStuService courseClassStuService;
    @Autowired
    private PageJdbcUtil pageJdbcUtil;
    @Autowired
    private CourseService courseService;
    @Autowired
    private LabReportService labReportService;
    @Autowired
    private UserService userService;

    public List<CourseClass> findCourseClassByCourseId(String courseId) {
        return courseClassRepository.findAllByDeleteFlagAndCourseId(
                DataValidity.VALID.getState(), courseId);
    }

    public void initCourseClass(String courseId, Long teacherId) {
        CourseClass courseClass = new CourseClass();
        courseClass.setId(UUID.randomUUID().toString());
        courseClass.setCourseId(courseId);
        courseClass.setTeacherId(teacherId);
        courseClassRepository.save(courseClass);
    }

    public Map<String, Object> save(List<CourseClassDomain> domainList,
                                    Long teacherId) {
        Map<String, Object> result = new HashMap<>();
        ArrayList<CourseClass> classList = new ArrayList<CourseClass>();
        ArrayList<CourseClassStu> classStuList = new ArrayList<CourseClassStu>();
        for (CourseClassDomain domain : domainList) {
            if (null != domain) {
                if (StringUtils.isEmpty(domain.getCourseId())) {
                    result.put(ApiReturnConstants.ERROR, "课程id不能为空！");
                    result.put(ApiReturnConstants.SUCCESS, false);
                    return result;
                }
                if (null != domain.getUserIds()
                        && !domain.getUserIds().isEmpty()) {

                    String courseClassId = "";
                    CourseClass courseClass = null;
                    if (!StringUtils.isEmpty(domain.getId())) {
                        courseClass = courseClassRepository
                                .findOne(domain.getId());
                        if (null != courseClass) {

                            courseClassId = domain.getId();

                            boolean count_result = stuClassIsExist(domain.getUserIds(), domain.getCourseId(), courseClassId);
                            HashSet<Long> userSet = new HashSet<>(domain.getUserIds());
                            if (domain.getUserIds().size()>userSet.size()){
                                count_result=true;
                            }
                            if (count_result) {
                                result.put(ApiReturnConstants.ERROR, "学生已存在!");
                                result.put(ApiReturnConstants.SUCCESS, false);
                                return result;
                            }

                            // 清空历史学生记录
                            courseClassStuService.deleteByCourseClassId(domain
                                    .getId());
                            labReportService.deleteByCourseClassId(domain
                                    .getId());

                        }
                    } else {
                        result.put(ApiReturnConstants.ERROR, "课程班级id不能为空！");
                        result.put(ApiReturnConstants.SUCCESS, false);
                        return result;
                    }

                    for (Long userId : domain.getUserIds()) {
                        CourseClassStu stu = new CourseClassStu();
                        stu.setId(UUID.randomUUID().toString());
                        stu.setStuId(userId);
                        stu.setCourseClassId(courseClassId);
                        stu.setCourseId(domain.getCourseId());
                        classStuList.add(stu);
                    }


                    // 更新选修班学生人数
                    courseClass.setStuNum(domain.getUserIds().size());
                    courseClassRepository.save(courseClass);

                } else if (null != domain.getClassId()
                        && domain.getClassId() > 0
                        && !StringUtils.isEmpty(domain.getCourseId())) {

                    Long countNum = courseClassRepository
                            .countByCourseIdAndClassIdAndDeleteFlag(
                                    domain.getCourseId(), domain.getClassId(),
                                    DataValidity.VALID.getState());
                    if (null != countNum && countNum > 0) {
                        result.put(ApiReturnConstants.ERROR, "添加班级信息已存在！");
                        result.put(ApiReturnConstants.SUCCESS, false);
                        return result;
                    }
                    CourseClass courseClass = new CourseClass();
                    String courseClassId = UUID.randomUUID().toString();
                    courseClass.setId(courseClassId);
                    courseClass.setCourseId(domain.getCourseId());
                    courseClass.setClassId(domain.getClassId());
                    courseClass.setProfessionalId(domain.getProfessionalId());
                    courseClass.setCollegeId(domain.getCollegeId());
                    courseClass.setTeacherId(teacherId);

                    List<Long> userIds = userService.getUserIdByClassId(domain
                            .getClassId());
                    if (null != userIds && userIds.size() > 0) {
                        boolean count_result = stuClassIsExist(userIds, domain.getCourseId(), courseClassId);
                        if (count_result) {
                            result.put(ApiReturnConstants.ERROR, "添加的行政班中有的学生已在选修班中!");
                            result.put(ApiReturnConstants.SUCCESS, false);
                            return result;
                        }

                        courseClass.setStuNum(userIds.size());
                        classList.add(courseClass);
                        if (null != userIds && !userIds.isEmpty()) {
                            for (Long userId : userIds) {
                                CourseClassStu stu = new CourseClassStu();
                                stu.setId(UUID.randomUUID().toString());
                                stu.setStuId(userId);
                                stu.setCourseClassId(courseClassId);
                                stu.setCourseId(domain.getCourseId());
                                classStuList.add(stu);
                            }
                        }
                    } else {
                        result.put(ApiReturnConstants.ERROR, "添加的行政班中没有学生!");
                        result.put(ApiReturnConstants.SUCCESS, false);
                        return result;
                    }
                } else if (!StringUtils.isEmpty(domain.getId())) {

                    CourseClass courseClass = courseClassRepository
                            .findOne(domain.getId());
                    if (null != courseClass) {
                        // 清空历史学生记录
                        courseClassStuService.deleteByCourseClassId(domain
                                .getId());
                        labReportService.deleteByCourseClassId(domain
                                .getId());
                        // 更新选修班学生人数
                        courseClass.setStuNum(0);
                        courseClassRepository.save(courseClass);
                    }

                } else {

                    result.put(ApiReturnConstants.ERROR, "添加班级信息有误！");
                    result.put(ApiReturnConstants.SUCCESS, false);
                    return result;
                }
            }
        }

        if (!classList.isEmpty()) {
            courseClassRepository.save(classList);
            InitLabReportDTO initDTO = new InitLabReportDTO();
            initDTO.setClassList(classList);
            InitThread thread = new InitThread(initDTO);
            thread.start();
        }
        if (!classStuList.isEmpty()) {
            courseClassStuService.save(classStuList);
            CourseClassDomain domain = domainList.get(0);
            if (null != domain.getUserIds()
                    && !domain.getUserIds().isEmpty()) {
                InitLabReportDTO initDTO = new InitLabReportDTO();
                initDTO.setTeacherId(teacherId);
                initDTO.setUserIdList(domain.getUserIds());
                initDTO.setCourseId(domain.getCourseId());
                initDTO.setCourseClassId(domain.getId());
                InitThread thread = new InitThread(initDTO);
                thread.start();
            }
        }
        result.put(ApiReturnConstants.SUCCESS, true);

        return result;
    }

    public void initClassStu() {

        ArrayList<CourseClassStu> classStuList = new ArrayList<CourseClassStu>();

        List<CourseClass> courseClassList = courseClassRepository
                .findAllByDeleteFlagAndClassIdNotNull(DataValidity.VALID
                        .getState());
        for (CourseClass courseClass : courseClassList) {
            courseClassStuService.deleteByCourseClassId(courseClass.getId());
            List<Long> userIds = userService.getUserIdByClassId(courseClass
                    .getClassId());
            if (null != userIds && !userIds.isEmpty()) {
                for (Long userId : userIds) {
                    CourseClassStu stu = new CourseClassStu();
                    stu.setId(UUID.randomUUID().toString());
                    stu.setStuId(userId);
                    stu.setCourseClassId(courseClass.getId());
                    stu.setCourseId(courseClass.getCourseId());
                    classStuList.add(stu);
                }
            }
        }
        if (!classStuList.isEmpty()) {
            courseClassStuService.save(classStuList);
        }
        courseClassRepository.initClassStuNum();
        courseClassStuService.initCourseId();
    }

    private boolean stuClassIsExist(List<Long> userIdsList, String courseId, String courseClassId) {
        String userIds = "";
        for (Long userId : userIdsList) {
            if (StringUtils.isEmpty(userIds)) {
                userIds = "" + userId;
            } else {
                userIds += "," + userId;
            }
        }
        String count_sql = "select count(*) from `t_course_class_stu` ccs where ccs.course_id ='" + courseId + "' and ccs.stu_id in("
                + userIds + ") and ccs.course_class_id !='" + courseClassId + "' and ccs.delete_flag =" + DataValidity.VALID.getState();
        Long result_num = pageJdbcUtil.getCount(count_sql);
        if (null != result_num && result_num > 0) {
            return true;
        }
        return false;
    }

    class InitThread extends Thread {

        private InitLabReportDTO dto;

        public InitThread(InitLabReportDTO dto) {
            this.dto = dto;
        }

        @Override
        public void run() {
            try {
                if (null != dto.getClassList() && !dto.getClassList().isEmpty()) {
                    labReportService.initClassLabReport(dto.getClassList());
                }
                if (null != dto.getUserIdList()
                        && !dto.getUserIdList().isEmpty()) {
                    labReportService.initStuLabReport(dto.getTeacherId(),
                            dto.getCourseId(), dto.getCourseClassId(),
                            dto.getUserIdList());
                }
            } catch (Exception ex) {
                log.debug("初始化实验报告数据异常......");
                ex.printStackTrace();
            }
        }
    }

    public Map<String, Object> delete(String courseClassId) {
        Map<String, Object> result = new HashMap<>();
        CourseClass courseClass = courseClassRepository.findOne(courseClassId);
        if (courseClass != null) {
            courseClass.setDeleteFlag(DataValidity.INVALID.getState());
            courseClassRepository.save(courseClass);

            // 清空历史学生记录
            courseClassStuService.deleteByCourseClassId(courseClassId);
            labReportService.deleteByCourseClassId(courseClassId);
            result.put(ApiReturnConstants.SUCCESS, true);
        } else {
            result.put(ApiReturnConstants.SUCCESS, false);
            result.put(ApiReturnConstants.ERROR, "课程班级信息不存在！");
        }
        return result;
    }

    public Map<String, Object> query(Pageable pageable, String courseName,
                                     Long userId, String courseId) {
        Map<String, Object> result = new HashMap<>();
        Page<Course> coursePage = courseService.getPage(pageable, courseName,
                userId, courseId);
        List<Course> courseList = coursePage.getContent();
        ArrayList<CourseInfoDTO> courseInfoList = new ArrayList<CourseInfoDTO>();
        String courseIds = "";
        if (null != courseList && !courseList.isEmpty()) {
            for (Course course : courseList) {
                if (null != course) {
                    CourseInfoDTO dto = new CourseInfoDTO();
                    dto.setCourseId(course.getId());
                    dto.setCourseName(course.getName());
                    dto.setCreatedDate(course.getCreatedDate());
                    if (StringUtils.isEmpty(courseIds)) {
                        courseIds = "'" + course.getId() + "'";
                    } else {
                        courseIds += ",'" + course.getId() + "'";
                    }
                    courseInfoList.add(dto);
                }
            }
        }
        if (!StringUtils.isEmpty(courseIds)) {
            List<CourseClassDTO> classList = findCourseClassList(courseIds);
            for (CourseInfoDTO courseInfoDTO : courseInfoList) {
                if (null != courseInfoDTO) {
                    for (CourseClassDTO classDto : classList) {
                        if (courseInfoDTO.getCourseId().equals(
                                classDto.getCourseId())) {
                            courseInfoDTO.getCourseClassList().add(classDto);
                        }
                    }
                }
            }
        }
        PageDomain p = new PageDomain();
        p.setPageNumber(pageable.getPageNumber());
        p.setPageSize(pageable.getPageSize());
        p.setTotalPages(coursePage.getTotalPages());
        p.setTotalElements(coursePage.getTotalElements());
        result.put(ApiReturnConstants.PAGE, p);
        result.put(ApiReturnConstants.DATA, courseInfoList);
        result.put(ApiReturnConstants.SUCCESS, true);
        return result;
    }

    RowMapper<CourseClassDTO> rm = new RowMapper<CourseClassDTO>() {

        @Override
        public CourseClassDTO mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            CourseClassDTO dto = new CourseClassDTO();
            dto.setCourseId(rs.getString("course_id"));
            dto.setCourseClassId(rs.getString("id"));
            dto.setClassName(rs.getString("class_name"));
            dto.setClassId(rs.getLong("class_id"));
            dto.setCollegeId(rs.getLong("college_id"));
            dto.setCollegeName(rs.getString("college_name"));
//			if (null != dto.getClassId() && dto.getClassId() > 0) {
//				dto.setStuNum(rs.getInt("class_stu_num"));
//			} else {
            dto.setStuNum(rs.getInt("stu_num"));
//			}

            return dto;
        }
    };

//	public List<CourseClassDTO> findCourseClassList(String courseIds) {
//
//		String querySql = "SELECT cc.`id`,cc.course_id,cc.class_id,cl.`name` AS class_name,cc.college_id,co.`name` AS college_name,cc.stu_num,(SELECT count(*) FROM `t_user` u WHERE u.delete_flag = 0	AND u.CLASS_ID = cc.class_id) AS class_stu_num FROM	`t_course_class` cc LEFT JOIN `t_college` co ON cc.COLLEGE_ID = co.ID LEFT JOIN `t_classes` cl ON cc.CLASS_ID = cl.ID WHERE cc.delete_flag = 0  ";
//		if (!StringUtils.isEmpty(courseIds)) {
//			querySql += " AND cc.course_id IN ( " + courseIds + ")";
//		}
//		querySql += " order by cc.created_date desc";
//		return pageJdbcUtil.getInfo(querySql, rm);
//	}

    public List<CourseClassDTO> findCourseClassList(String courseIds) {

        String querySql = "SELECT cc.`id`,cc.course_id,cc.class_id,cl.`name` AS class_name,cc.college_id,co.`name` AS college_name,cc.stu_num FROM	`t_course_class` cc LEFT JOIN `t_college` co ON cc.COLLEGE_ID = co.ID LEFT JOIN `t_classes` cl ON cc.CLASS_ID = cl.ID WHERE cc.delete_flag = 0  ";
        if (!StringUtils.isEmpty(courseIds)) {
            querySql += " AND cc.course_id IN ( " + courseIds + ")";
        }
        querySql += " order by cc.created_date,cc.course_id desc";
        return pageJdbcUtil.getInfo(querySql, rm);
    }

    public List<CourseClassDTO> findMyCourseClassList(String courseId, Long teacherId) {

        String querySql = "SELECT cc.`id`,cc.course_id,cc.class_id,cl.`name` AS class_name,cc.college_id,co.`name` AS college_name,cc.stu_num FROM	`t_course_class` cc LEFT JOIN `t_college` co ON cc.COLLEGE_ID = co.ID  JOIN `t_classes` cl ON cc.CLASS_ID = cl.ID WHERE cc.delete_flag = 0  and cc.teacher_id = " + teacherId;
        if (!StringUtils.isEmpty(courseId)) {
            querySql += " AND cc.course_id =  '" + courseId + "'";
        }
        querySql += " order by cc.created_date,cc.course_id desc";
        return pageJdbcUtil.getInfo(querySql, rm);
    }


    RowMapper<CourseClassDTO> stuNumRm = new RowMapper<CourseClassDTO>() {

        @Override
        public CourseClassDTO mapRow(ResultSet rs, int rowNum)
                throws SQLException {
            // TODO Auto-generated method stub
            CourseClassDTO dto = new CourseClassDTO();
            dto.setStuNum(rs.getInt("stu_num"));
            return dto;
        }
    };


    public List<CourseClassDTO> sumCourseClassStuNum(String courseClassIds) {

        String querySql = "select sum(cc.stu_num) as stu_num from `t_course_class` cc where cc.id =  '" + courseClassIds + "'";

        return pageJdbcUtil.getInfo(querySql, stuNumRm);
    }

    public CourseClass findCourseClass(String courseId, Long classId) {
        return courseClassRepository.findByCourseIdAndClassIdAndDeleteFlag(courseId, classId, DataValidity.VALID.getState());
    }

    public CourseClass findCourseClass(String id) {
        return courseClassRepository.findOne(id);
    }

    public List<CourseClass> findCourseClass() {
        String querySql = "SELECT cc.`id`,cc.course_id,cc.class_id,cl.`name` AS class_name,cc.college_id,co.`name` AS college_name,cc.stu_num FROM	`t_course_class` cc LEFT JOIN `t_college` co ON cc.COLLEGE_ID = co.ID LEFT JOIN `t_classes` cl ON cc.CLASS_ID = cl.ID WHERE cc.delete_flag = 0  ";
        return null;
    }
    public Integer getStuNum(String courseId,Long classId){
		CourseClass courseClass = courseClassRepository.findByCourseIdAndClassIdAndDeleteFlag(courseId, classId, DataValidity.VALID.getState());
		if (Objects.isNull(courseClass)){
		    return 0;
        }
		return courseClass.getStuNum();
	}
}
